#pragma once

#include "Dream/Core/PlatformDetection.h"

#include <memory>

#ifdef DM_PLAT_WIN
	#ifdef DM_BUILD_DLL
		#define DM_API __declspec(dllexport)
	#else
		#define DM_API __declspec(dllimport)
	#endif // DM_BUILD_DLL
#else
	#error "Dream only supports Windows!"
#endif // DM_PLAT_WIN

#ifdef DM_DEBUG
	#define DM_ENABLE_ASSERTS
#endif // DM_DEBUG

#ifdef DM_ENABLE_ASSERTS
	#define DM_ASSERT(x, ...) { if(!(x)) { DM_ERROR("Assertion Failed: {0}", __VA_ARGS__); __debugbreak(); } }
	#define DM_CORE_ASSERT(x, ...) { if(!(x)) { DM_CORE_ERROR("Assertion Failed: {0}", __VA_ARGS__); __debugbreak(); } }
#else
	#define DM_ASSERT(x, ...)
	#define DM_CORE_ASSERT(x, ...)
#endif

#define BIT(x) (1 << x)

#define DM_BIND_EVENT_FN(fn) std::bind(&fn, this, std::placeholders::_1)

namespace Dream
{


	template<typename T>
	using Scope = std::unique_ptr<T>;
	template<typename T, typename ... Args>
	constexpr Scope<T> MakeScope(Args&& ... args)
	{
		return std::make_unique<T>(std::forward<Args>(args)...);
	}

	template<typename T>
	using Ref = std::shared_ptr<T>;
	template<typename T, typename ... Args>
	constexpr Ref<T> MakeRef(Args&& ... args)
	{
		return std::make_shared<T>(std::forward<Args>(args)...);
	}
}